<?php


namespace App\Rules;


use Illuminate\Contracts\Validation\Rule;

class IdCard implements Rule
{

    const CITY_CODES = [
        11 => "北京",
        12 => "天津",
        13 => "河北",
        14 => "山西",
        15 => "内蒙古",
        21 => "辽宁",
        22 => "吉林",
        23 => "黑龙江 ",
        31 => "上海",
        32 => "江苏",
        33 => "浙江",
        34 => "安徽",
        35 => "福建",
        36 => "江西",
        37 => "山东",
        41 => "河南",
        42 => "湖北 ",
        43 => "湖南",
        44 => "广东",
        45 => "广西",
        46 => "海南",
        50 => "重庆",
        51 => "四川",
        52 => "贵州",
        53 => "云南",
        54 => "西藏 ",
        61 => "陕西",
        62 => "甘肃",
        63 => "青海",
        64 => "宁夏",
        65 => "新疆",
        71 => "台湾",
        81 => "香港",
        82 => "澳门",
        91 => "国外 "
    ];
    const FACTOR = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2];

    const PARITY = [1, 0, 'X', 9, 8, 7, 6, 5, 4, 3, 2];

    /**
     * @inheritDoc
     */
    public function passes($attribute, $code)
    {
        if (!preg_match("/^\d{6}(18|19|20)?\d{2}(0[1-9]|1[012])(0[1-9]|[12]\d|3[01])\d{3}(\d|X)$/i", $code)) {
            return false;
        }
        if (!isset(self::CITY_CODES[substr($code, 0, 2)])) {
            return false;
        }

        $sum = 0;
        $ai = 0;
        $wi = 0;
        for ($i = 0; $i < 17; $i++) {
            $ai = $code[$i];
            $wi = self::FACTOR[$i];
            $sum += $ai * $wi;
        }
        if (self::PARITY[$sum % 11] != $code[17]) {
            return false;
        }
        return true;
    }

    /**
     * @inheritDoc
     */
    public function message()
    {
        return '身份证号码格式错误';
    }
}
